package dao

import (
	"chat_srv/basic/config"
	chat "chat_srv/basic/proto"
	"chat_srv/handler/model"
	"context"
	"fmt"
	"log"
	"strconv"
	"time"
)

// 生成会话id
func GenerateConversationId(user1, user2, convType int64) string {
	// 私聊
	if convType == 1 {
		// 私聊：按大小排序生成固定ID
		minID := user1
		maxID := user2
		if user1 > user2 {
			minID = user2
			maxID = user1
		}
		return fmt.Sprintf("single_%d_%d", minID, maxID)
	} else {
		// 群聊：user2应该是群ID
		return fmt.Sprintf("group_%d", user2)
	}
}

// 生成消息序列号
func GenerateSeq(conversationId string) (int64, error) {
	key := fmt.Sprintf("conversation:%s:seq", conversationId)
	return config.Rdb.Incr(config.Ctx, key).Result()
}

// 创建新会话
func CreateNewConversation(conversationId string, user1, user2, convType int64) (model.ImConversation, error) {
	// 开启事务，创建会话并添加会话成员
	tx := config.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 创建会话
	conversation := model.ImConversation{
		ConversationId:   conversationId,
		ConversationType: uint(convType),
		MemberCount:      2,
		CreatedAt:        time.Now(),
		UpdatedAt:        time.Now(),
	}

	if err := conversation.Create(tx); err != nil {
		tx.Rollback()
		return model.ImConversation{}, fmt.Errorf("创建会话失败：%w", err)
	}

	// 添加会话成员
	members := []model.ImConversationMember{
		{
			ConversationId: conversationId,
			UserId:         uint(user1),
			JoinedAt:       time.Now(),
		},
		{
			ConversationId: conversationId,
			UserId:         uint(user2),
			JoinedAt:       time.Now(),
		},
	}

	if err := tx.Create(&members).Error; err != nil {
		tx.Rollback()
		return model.ImConversation{}, fmt.Errorf("添加会话成员失败：%w", err)
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		tx.Rollback()
		return model.ImConversation{}, fmt.Errorf("提交事务失败：%w", err)
	}

	return conversation, nil
}

// 查询或创建会话
func GetOrCreateConversationSimple(conversationId string, user1, user2, convType int64) (model.ImConversation, error) {
	// 查询现有的会话
	var conversation model.ImConversation
	err := conversation.GetImConversation(conversationId)
	if err != nil {
		return model.ImConversation{}, fmt.Errorf("查询会话失败：%w", err)
	}

	if conversation.Id == 0 {
		// 会话不存在，创建新会话
		return CreateNewConversation(conversationId, user1, user2, convType)
	}
	// 会话已存在，直接返回
	return conversation, nil
}

// 发送消息
func SendMessage(_ context.Context, in *chat.SendMessageReq) (*model.ImMessage, error) {
	// 参数校验
	if in.FormUserId == 0 || in.ToTargetId == 0 || in.Content == "" {
		return nil, fmt.Errorf("参数不完整")
	}
	// 生成会话id
	conversationId := GenerateConversationId(in.FormUserId, in.ToTargetId, config.ConversationTypePrivate)

	// 查询或创建会话
	conversation, err := GetOrCreateConversationSimple(conversationId, in.FormUserId, in.ToTargetId, in.MessageType)
	if err != nil {
		return nil, fmt.Errorf("处理会话失败：%w", err)
	}

	// 生成序列号
	seq, err := GenerateSeq(conversation.ConversationId)
	if err != nil {
		return nil, fmt.Errorf("生成序列号失败：%w", err)
	}

	// 创建消息
	message := &model.ImMessage{
		ConversationId: conversation.ConversationId,
		FormUserId:     uint(in.FormUserId),
		ToTargetId:     strconv.FormatInt(in.ToTargetId, 10),
		Content:        in.Content,
		MessageType:    uint(in.MessageType),
		Status:         config.MessageStatusDelivered, // 已发送
		Seq:            uint(seq),
		SendTime:       time.Now(),
		CreatedAt:      time.Now(),
	}

	// 保存消息
	if err = message.Create(); err != nil {
		return nil, fmt.Errorf("保存消息失败：%w", err)
	}

	// 更新会话最后一条消息id和最后序列号
	updateData := map[string]interface{}{
		"last_message_id": message.Id,
		"last_seq":        message.Seq,
		"updated_at":      time.Now(),
	}
	if err = conversation.Update(conversationId, updateData); err != nil {
		log.Printf("更新会话失败: %v", err)
	}
	return message, nil
}

// 获取会话消息
func GetConversationMessages(_ context.Context, in *chat.GetMessageReq) ([]*chat.Message, error) {
	// 查询会话消息
	var imMessage model.ImMessage
	imMessages, err := imMessage.GetConversationMessages(&model.ImMessage{ConversationId: in.GetConversationId()})
	if err != nil {
		return nil, fmt.Errorf("查询会话消息失败：%w", err)
	}

	// 转换为pb消息
	var imMessageList []*chat.Message
	for _, message := range imMessages {
		list := chat.Message{
			Id:             int64(message.Id),
			ConversationId: message.ConversationId,
			FormUserId:     int64(message.FormUserId),
			ToTargetId:     message.ToTargetId,
			Content:        message.Content,
			MessageType:    int64(message.MessageType),
			SendTime:       message.SendTime.Format(time.DateTime),
		}
		imMessageList = append(imMessageList, &list)
	}
	return imMessageList, nil
}
